<script>
import T from 'ant-design-vue/es/table/Table'
import Vue from 'vue'
export default {
  name: 'CustomTable',
  props: Object.assign({}, T.props, {
    showAlert: {
      type: Boolean,
      default: true,
    },
    showPagination: {
      type: Boolean,
      default: true,
    },
    showSelection: {
      type: Boolean,
      default: true,
    },
    showHeader: {
      type: Boolean,
      default: true,
    },
    // 是否显示自定义列设置
    showColSettings: {
      type: Boolean,
      default: false,
    },
    selectionType: {
      type: String,
      default: 'checkbox',
    },
    rowKey: {
      type: String,
      default: 'id',
    },
    dataSource: {
      type: [Object, Array],
      required: true,
      default() {
        return {
          total: 0,
          current: 1,
          size: 10,
          records: [],
        }
      },
    },
    hideColumns: {
      type: Array,
      default() {
        return []
      },
    },
    // 不进行自定义列设置的字段，dataIndex或者key值
    hideColSettings: {
      type: Array,
      default() {
        return []
      },
    },
    // 初始化自定义列关闭状态的字段，dataIndex或者key值
    defaultCloseColSettings: {
      type: Array,
      default() {
        return []
      },
    },
    onChange: {
      type: Function,
      default: null,
    },
    onRowClick: {
      type: Function,
      default: null,
    },
    // 指定每页可以显示多少条
    pageSizeOptions: {
      type: Array,
      default() {
        return ['10', '20', '30', '40']
      },
    },
  }),
  data() {
    return {
      selectedRows: [],
      selectedRowKeys: [],
      settingColumns: [],
      colSearchValue: null,
    }
  },
  computed: {
    pageInfo() {
      return {
        showSizeChanger: true,
        showQuickJumper: true,
        pageSizeOptions: this.pageSizeOptions,
        total: Number(this.dataSource.total) || 0,
        showTotal: (total) => `共 ${total} 条`,
        current: Number(this.dataSource.currentPage || this.dataSource.current) || 1,
        pageSize: Number(this.dataSource.pageSize || this.dataSource.size) || 10,
      }
    },
    customColumns: (state) => {
      if (state.hideColumns && state.hideColumns.length > 0) {
        return state.columns.filter((item) => {
          if (item.dataIndex) {
            return !state.hideColumns.includes(item.dataIndex)
          } else if (item.title) {
            return !state.hideColumns.includes(item.title)
          } else {
            return true
          }
        })
      } else {
        return state.columns
      }
    },
    customColcolumns() {
      const cols = this.customColumns.filter((item) => {
        if (this.hideColSettings.includes(item.dataIndex) || this.hideColSettings.includes(item.key)) {
          return true
        }
        if (this.settingColumns.includes(item.dataIndex)) {
          return true
        }
        return false
      })
      if (this.showColSettings) {
        return cols
      } else {
        return this.customColumns
      }
    },
  },
  watch: {
    customColumns: {
      immediate: true,
      handler(val) {
        if (val) {
          // 初始化列设置
          const key = this.$route.name + ':ColSettings'
          let colSettings = Vue.ls.get(key.toUpperCase())
          if (colSettings == null || colSettings == undefined) {
            let allSettingColumns = []
            this.customColumns.forEach((item) => {
              if (!this.defaultCloseColSettings.includes(item.dataIndex)) {
                allSettingColumns.push(item.dataIndex)
              }
            })
            this.settingColumns = allSettingColumns
          } else {
            this.settingColumns = colSettings
          }
        }
      },
    },
  },
  methods: {
    getSelectedRowKeys() {
      return this.selectedRowKeys
    },
    getSelectedRows() {
      return this.selectedRows
    },
    onClearRowKeys() {
      // 清空选中内容
      this.selectedRowKeys = []
      this.selectedRows = []
      this.$emit('selectedRow', this.selectedRowKeys)
    },
    onSelectChange(selectedRowKeys, selectedRows) {
      // console.log(selectedRows)
      // 选中内容
      this.selectedRowKeys = selectedRowKeys
      if (this.rowKey) {
        // 分页数据选择selectedRows只返回当前页的数据，需要特殊处理。1合并数据，2过滤出已选中的数据，3去重
        let map = new Map()
        this.selectedRows = [...this.selectedRows, ...selectedRows]
          .filter((item) => this.selectedRowKeys.includes(item[this.rowKey]))
          .reduce((item, next) => {
            if (!map.has(next[this.rowKey])) {
              map.set(next[this.rowKey], true)
              item.push(next)
            }
            return item
          }, [])
      }
      // console.log(this.selectedRows)
      // console.log(this.selectedRowKeys)
      this.$emit('selectedRow', this.selectedRows)
      this.$emit('selectedRowKeys', this.selectedRowKeys)
    },
    onSelect(record, selected, selectedRows, nativeEvent) {
      this.$emit('rowSelect', record, selected, selectedRows)
    },
    onTableChange(pagination, filters, sorter) {
      // 表格分页、过滤、排序变化的时候触发change回调
      const query = {
        pageNo: pagination.current,
        pageSize: pagination.pageSize,
        sortField: sorter.field,
        sortOrder: sorter.order,
        ...filters,
      }
      this.onChange && this.onChange(query)
      this.$emit('change', query)
    },
    onCustomRow(record) {
      return {
        on: {
          click: (e) => {
            e.preventDefault()
            this.onRowClick && this.onRowClick(record)
            this.$emit('rowClick', record)
          },
        },
      }
    },
    // 列设置更改事件
    onColSettingsChange(checkedValues) {
      const key = this.$route.name + ':ColSettings'
      Vue.ls.set(key.toUpperCase(), checkedValues, 7 * 24 * 60 * 60 * 1000)
      this.settingColumns = checkedValues
    },
    renderAlert() {
      // 绘制统计列数据
      return (
        <a-alert class="table-alert">
          <div slot="message" class="table-alert-info">
            <div class="table-alert-info-content">
              <span style="margin-right: 12px">
                已选择 <a style="font-weight: 600">{this.selectedRowKeys.length}</a> 项
              </span>
            </div>
            {this.selectedRowKeys.length > 0 && (
              <div class="table-alert-info-option">
                <a onClick={this.onClearRowKeys}>清空</a>
              </div>
            )}
          </div>
        </a-alert>
      )
    },
    renderSettingColumns() {
      // 自定义列，可通过插槽自定义配置模板
      // 如：
      // <template v-slot:colSettings>
      //  <a-button class="table-custom-cols">
      //    <a-icon type="setting" />设置
      //  </a-button>
      // </template>
      return (
        <a-popover title="自定义列" trigger="click" placement="leftBottom">
          <template slot="content">
            <a-checkbox-group
              v-model={this.settingColumns}
              defaultValue={this.settingColumns}
              on-change={this.onColSettingsChange}
            >
              <a-input-search placeholder="搜索字段" v-model={this.colSearchValue} />
              <a-row style="width: 400px;margin-top:6px;">
                {this.customColumns.map((item) => {
                  const title = item.slots && item.slots.title ? item.columnTitle : item.title
                  if (!this.hideColSettings.includes(item.dataIndex) && !this.hideColSettings.includes(item.key)) {
                    return (
                      <a-col
                        span={12}
                        class={{ curCol: this.colSearchValue && title.indexOf(this.colSearchValue) > -1 }}
                      >
                        <a-checkbox value={item.dataIndex}>
                          <j-ellipsis value={title} length={22} />
                        </a-checkbox>
                      </a-col>
                    )
                  }
                })}
              </a-row>
            </a-checkbox-group>
          </template>
          {this.$slots.colSettings ? (
            this.$slots.colSettings
          ) : (
            <a-button class="table-custom-cols">
              <a-icon type="setting" />
              字段配置
            </a-button>
          )}
        </a-popover>
      )
    },
  },
  render() {
    const {
      showAlert,
      showColSettings,
      showPagination,
      showSelection,
      showHeader,
      dataSource,
      onTableChange,
      pageInfo,
    } = this
    const rowSelection = {
      selectedRowKeys: this.selectedRowKeys,
      onChange: this.onSelectChange,
      type: this.selectionType,
      onSelect: this.onSelect,
    }
    let props = {}
    Object.keys(T.props).forEach((key) => {
      if (key === 'dataSource') {
        props[key] = dataSource instanceof Array ? dataSource : dataSource.records
      } else if (key === 'rowSelection') {
        // props[key] = showSelection ? rowSelection : null;
        props[key] = showSelection ? Object.assign(rowSelection, this[key]) : null
      } else if (key === 'showHeader') {
        props[key] = showHeader
      } else if (key === 'pagination') {
        props[key] = showPagination && !(dataSource instanceof Array) ? Object.assign(pageInfo, this[key]) : false
      } else if (key === 'customRow') {
        props[key] = this[key] || this.onCustomRow
      } else if (key === 'columns') {
        props[key] = this.customColcolumns
      } else {
        this[key] && (props[key] = this[key])
      }
    })
    return (
      <div class="table">
        {showAlert && showColSettings ? (
          <div class="table-handle">
            {this.renderAlert()} {this.renderSettingColumns()}
          </div>
        ) : showAlert && !showColSettings ? (
          <div class="table-handle"> {this.renderAlert()}</div>
        ) : !showAlert && showColSettings ? (
          <div class="table-handle"> {this.renderSettingColumns()}</div>
        ) : null}
        <a-table {...{ props, scopedSlots: { ...this.$scopedSlots } }} onChange={onTableChange}>
          {Object.keys(this.$slots).map((name) => (
            <template slot={name}>{this.$slots[name]}</template>
          ))}
        </a-table>
      </div>
    )
  },
}
</script>

<style scoped lang="less">
:deep(.ant-table-body > table) {
  border-top: 1px solid #e8e8e8;
}
.table {
  position: relative;
  .table-alert {
    margin-bottom: 16px;
    .table-alert-info {
      display: flex;
      .table-alert-info-content {
        flex: 1 1;
      }
      .table-alert-info-option {
        min-width: 48px;
        padding-left: 16px;
      }
    }
    button[role='switch'] * {
      z-index: 999;
    }
  }
  :deep(.ant-table) {
    .ant-table-body {
      overflow-x: auto !important;
    }
    // 缩小表格左右边距
    .ant-table-thead > tr > th,
    .ant-table-tbody > tr > td {
      padding-left: 4px;
      padding-right: 4px;
    }
    .ant-table-thead > tr:first-child > th:first-child,
    .ant-table-tbody > tr > td:first-child {
      padding-left: 10px;
      padding-right: 10px;
    }
  }
  .table-custom-cols {
    position: absolute;
    right: 0;
    top: -40px;
    z-index: 8;
  }
}
:deep(.curCol) {
  label {
    color: #1890ff;
  }
}
</style>
